using System;
using System.Collections.Generic;
using System.Text.Json;
using Engine;
using Game;
using GameEntitySystem;

namespace DiggusMaximus
{
    /// <summary>
    /// DiggusMaximusMod 是一个实现连锁挖掘功能的模组类。
    /// 当玩家挖掘一个方块时，该模组会自动检测周围相同类型的方块并进行连锁挖掘。
    /// </summary>
    public class DiggusMaximusMod : ModLoader
    {
        private SubsystemTerrain _terrain;
        private SubsystemPickables _pickables;
        private SubsystemParticles _particles;
        private ChainSettings _settings;
        private List<Point3> _chainPoints = new List<Point3>();

        /// <summary>
        /// 初始化模组，注册钩子并设置默认配置。
        /// </summary>
        public override void __ModInitialize()
        {
            ModsManager.RegisterHook("OnBlockDug", this);
            ModsManager.RegisterHook("OnProjectLoaded", this);
            ModsManager.RegisterHook("UpdateInput", this);
            string configJson = ContentManager.Get<string>("DismembermentConfig", ".json");
            // 初始化链式设置配置
            // 该配置用于控制链式反应的相关参数
            if (configJson != null)
            {
                _settings = JsonSerializer.Deserialize<ChainSettings>(configJson);
            }
            else
            {
                Log.Error("连锁使用默认设置");
                _settings = new ChainSettings
                {
                    Enabled = true,           // 启用链式反应功能
                    MaxChainBlocks = 50,      // 设置最大链式方块数量为50
                    ConsumeDurability = true, // 消耗耐久度
                    ShowBreakParticles = true // 显示破坏粒子效果
                };
            }
            Log.Information("[DiggusMaximus] 连锁功能已加载");
        }

        /// <summary>
        /// 当项目加载完成时，获取必要的子系统引用。
        /// </summary>
        /// <param name="project">当前加载的游戏项目。</param>
        public override void OnProjectLoaded(Project project)
        {
            _terrain = project.FindSubsystem<SubsystemTerrain>(true);
            _pickables = project.FindSubsystem<SubsystemPickables>(true);
            _particles = project.FindSubsystem<SubsystemParticles>(true);
        }

        /// <summary>
        /// 当玩家挖掘一个方块时触发，执行连锁挖掘逻辑。
        /// </summary>
        /// <param name="miner">执行挖掘操作的矿工组件。</param>
        /// <param name="digData">挖掘的方块数据。</param>
        /// <param name="cellValue">被挖掘方块的单元格值。</param>
        /// <param name="durabilityReduction">工具耐久度减少量的引用。</param>
        /// <param name="mute">是否静音挖掘音效的引用。</param>
        /// <param name="playerDataDugAdd">玩家挖掘数据增加量的引用。</param>
        public override void OnBlockDug(ComponentMiner miner, BlockPlacementData digData, int cellValue,
            ref int durabilityReduction, ref bool mute, ref int playerDataDugAdd)
        {
            // 如果连锁挖掘功能未启用，则直接返回
            if (!_settings.Enabled) return;

            int targetBlockId = Terrain.ExtractContents(cellValue);
            var tool = BlocksManager.Blocks[Terrain.ExtractContents(miner.ActiveBlockValue)];
            int remainingDurability = tool.GetDurability(miner.ActiveBlockValue) - tool.GetDamage(miner.ActiveBlockValue);

            _chainPoints.Clear();
            // 收集相邻的相同类型方块
            CollectAdjacentBlocks(digData.CellFace.Point, targetBlockId, remainingDurability);

            // 如果没有收集到任何方块，则直接返回
            if (_chainPoints.Count == 0) return;

            // 处理连锁挖掘的掉落物和效果
            ProcessChainDrops(miner, targetBlockId, cellValue, ref durabilityReduction);
            mute = false;
        }

        /// <summary>
        /// 使用广度优先搜索（BFS）算法收集与起始点相邻的相同类型方块。
        /// </summary>
        /// <param name="startPoint">起始挖掘点。</param>
        /// <param name="targetBlockId">目标方块的ID。</param>
        /// <param name="maxBlocks">最大挖掘方块数量。</param>
        private void CollectAdjacentBlocks(Point3 startPoint, int targetBlockId, int maxBlocks)
        {
            var queue = new Queue<Point3>();
            var visited = new HashSet<Point3>();

            queue.Enqueue(startPoint);
            visited.Add(startPoint);

            // BFS遍历相邻方块
            while (queue.Count > 0 && _chainPoints.Count < maxBlocks && _chainPoints.Count < _settings.MaxChainBlocks)
            {
                var current = queue.Dequeue();

                for (int x = -1; x <= 1; x++)
                    for (int y = -1; y <= 1; y++)
                        for (int z = -1; z <= 1; z++)
                        {
                            // 跳过自身
                            if (x == 0 && y == 0 && z == 0) continue;

                            var neighbor = new Point3(current.X + x, current.Y + y, current.Z + z);
                            // 如果已经访问过该点，则跳过
                            if (visited.Contains(neighbor)) continue;

                            int cell = _terrain.Terrain.GetCellValue(neighbor.X, neighbor.Y, neighbor.Z);
                            int blockId = Terrain.ExtractContents(cell);

                            // 如果是目标方块，则加入连锁列表
                            if (blockId == targetBlockId)
                            {
                                visited.Add(neighbor);
                                _chainPoints.Add(neighbor);
                                queue.Enqueue(neighbor);
                            }
                        }
            }
        }

        /// <summary>
        /// 处理连锁挖掘产生的掉落物、粒子效果以及耐久度消耗。
        /// </summary>
        /// <param name="miner">执行挖掘操作的矿工组件。</param>
        /// <param name="targetBlockId">目标方块的ID。</param>
        /// <param name="originalCellValue">原始方块的单元格值。</param>
        /// <param name="durabilityReduction">工具耐久度减少量的引用。</param>
        private void ProcessChainDrops(ComponentMiner miner, int targetBlockId, int originalCellValue,
            ref int durabilityReduction)
        {
            var block = BlocksManager.Blocks[targetBlockId];
            var dropPoint = miner.Entity.FindComponent<ComponentBody>().Position;
            int X = (int)miner.Entity.FindComponent<ComponentBody>().Position.X;
            int Y = (int)miner.Entity.FindComponent<ComponentBody>().Position.Y;
            int Z = (int)miner.Entity.FindComponent<ComponentBody>().Position.Z;
            Point3 minerPosition = new Point3(X,Y,Z);

            // 遍历所有连锁挖掘的方块
            foreach (var point in _chainPoints)
            {
                int cellValue = _terrain.Terrain.GetCellValue(point.X, point.Y, point.Z);

                var dropValues = new List<BlockDropValue>();
                bool dropValid = false;
                block.GetDropValues(_terrain, cellValue, cellValue, 0, dropValues, out dropValid);

                // 生成掉落物
                foreach (var drop in dropValues)
                {
                    if (drop.Count <= 0) continue;
                    var pos = new Vector3(point.X + 0.5f, point.Y + 0.5f, point.Z + 0.5f);
                    _pickables.AddPickable(drop.Value, drop.Count, pos, null, null);
                }

                // 清除方块
                _terrain.ChangeCell(point.X, point.Y, point.Z, 0, true, null);

                // 显示破坏粒子效果
                if (_settings.ShowBreakParticles)
                {
                    var particles = block.CreateDebrisParticleSystem(_terrain, new Vector3(point), cellValue, 0.35f);
                    _particles.AddParticleSystem(particles, false);
                }
            }

            // 根据设置决定是否消耗工具耐久度
            durabilityReduction = _settings.ConsumeDurability ? _chainPoints.Count + 1 : 1;
        }
        public override void UpdateInput(ComponentInput componentInput, WidgetInput widgetInput)
        {
            if (widgetInput.IsKeyDownOnce(Engine.Input.Key.C))
            {
                // 切换连锁挖掘功能的启用状态
                _settings.Enabled = !_settings.Enabled;

                // 记录当前状态到日志
                Log.Error($"[DiggusMaximus] 连锁挖掘功能已{(_settings.Enabled ? "启用" : "禁用")}");
            }
        }
    }


    /// <summary>
    /// 连锁挖掘功能的配置设置类。
    /// </summary>
    public class ChainSettings
    {
        /// <summary>
        /// 是否启用连锁挖掘功能。
        /// </summary>
        [System.Text.Json.Serialization.JsonPropertyName("Enabled")]
        public bool Enabled { get; set; }

        /// <summary>
        /// 连锁挖掘的最大方块数量。
        /// </summary>
        [System.Text.Json.Serialization.JsonPropertyName("MaxChainBlocks")]
        public int MaxChainBlocks { get; set; }

        /// <summary>
        /// 是否在连锁挖掘时消耗工具耐久度。
        /// </summary>
        [System.Text.Json.Serialization.JsonPropertyName("ConsumeDurability")]
        public bool ConsumeDurability { get; set; }

        /// <summary>
        /// 是否显示方块破坏的粒子效果。
        /// </summary>
        [System.Text.Json.Serialization.JsonPropertyName("ShowBreakParticles")]
        public bool ShowBreakParticles { get; set; }
    }
}